package com.simplesoftwares.client.library.composite;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

import com.google.gwt.core.shared.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ValueBox;
import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
import com.google.gwt.user.client.ui.Widget;
import com.itextpdf.text.log.SysoCounter;
import com.simplesoftwares.client.library.FlexForm;
import com.simplesoftwares.client.library.FlexForm.FormStyle;
import com.simplesoftwares.client.library.FormField;
import com.simplesoftwares.client.library.FormFieldBuilder;
import com.simplesoftwares.client.library.appstructure.search.Filter;
import com.simplesoftwares.client.library.appstructure.search.MyQuerry;
import com.simplesoftwares.client.library.libservice.PersonInfoService;
import com.simplesoftwares.client.library.libservice.PersonInfoServiceAsync;

import com.slicktechnologies.shared.common.helperlayer.PersonInfo;
import com.slicktechnologies.shared.common.personlayer.Person;


// TODO: Auto-generated Javadoc
/**
 * The Class UploadComposite.Instance Comes with three {@link SuggestBox} id,count, cellNumber
 * corresponding to any {@link Person} object.
 * IF id is selected corresponding Name and cell phone number is get auto filled.Simmilar functionality 
 * for othe two suggest Box.
 * Underlying return type of composite is {@link PersonInfo}
 */
public class PersonInfoComposite extends  Composite implements HasValue<PersonInfo>,
SelectionHandler<Suggestion>,Editor<PersonInfo>,CompositeInterface
{
    private SuggestBox id;
    private SuggestBox name;
    private SuggestBox phone;
    private FormField customerId,customerName,customerCell;
    private boolean isValidate;
    
    /**
     * Gets the querry.
     *
     * @return the querry
     */
    public MyQuerry getQuerry() {
		return querry;
	}

	/**
	 * Sets the querry.
	 *
	 * @param querry the new querry
	 */
	public void setQuerry(MyQuerry querry) {
		this.querry = querry;
	}

	
	private PersonInfo centity;
    
    /** The id to person info Map */
    private   HashMap<Integer,PersonInfo>idToPersonInfo = new HashMap<Integer,PersonInfo>();
	
	/** The cell to person info Map */
	private   HashMap<Long,PersonInfo>cellToPersonInfo = new HashMap<Long,PersonInfo>();
	
	/** The name to person info Map */
	private   HashMap<String,PersonInfo>nameToPersonInfo = new HashMap<String,PersonInfo>();
	
	/** The service. */
	final PersonInfoServiceAsync service=GWT.create(PersonInfoService.class);
	
	/** The querry. */
	MyQuerry querry;
	
    /** The panel. */
    private FlowPanel panel;
    
    /** The ff. */
    private FormField[][]formfield;
    private boolean mandatory;
	
	
	/**
	 * Instantiates a new person info composite.
	 *
	 * @param querry the querry
	 */
	public PersonInfoComposite(MyQuerry querry) 
	{
		super();
		mandatory=true;
		createForm();
		this.querry=querry;
		initalizePersonInfoHashMaps();
		initWidget(panel);
		isValidate=true;
		applyStyle();
		
	}
	
	public PersonInfoComposite(MyQuerry querry,boolean mode) 
	{
		super();
		createForm();
		this.querry=querry;
		initalizePersonInfoHashMaps();
		initWidget(panel);
		mandatory=false;
		isValidate=true;
		applyStyle();
	}
	
	/**
	 * Initializewidgets.
	 */
	private void initializewidgets()
	{
		id=new SuggestBox();
		id.addSelectionHandler(this);
		
		name=new SuggestBox();
		name.addSelectionHandler(this);
		
		phone=new SuggestBox();
		phone.addSelectionHandler(this);	
		
		id.getValueBox().addKeyPressHandler(new NumbersOnly());
		phone.getValueBox().addKeyPressHandler(new NumbersOnly());
		
	}
	
	/**
	 * Creates the UI
	 */
	public void createForm()
	{
		initializewidgets();
		FormFieldBuilder builder;
	    
	    System.out.println("Mandatory is "+this.mandatory);
	    if(mandatory==true)
	    {
	      builder= new FormFieldBuilder("* Id",id);
	      customerId=builder.setMandatory(true).setMandatoryMsg("These fields are mandatory!").build();
	      builder=new FormFieldBuilder("* Name",name);
		    customerName=builder.setMandatory(true).build();
		    builder=new FormFieldBuilder("* Cell Number",phone);
		    customerCell=builder.setMandatory(true).build();	
	      
	    }
	    else
	    {
	    	builder= new FormFieldBuilder("Id",id);
	    	customerId=builder.setMandatory(true).setMandatoryMsg("These fields are mandatory!").build();
		    builder=new FormFieldBuilder("Name ",name);
			customerName=builder.setMandatory(true).build();
			builder=new FormFieldBuilder("Cell Number",phone);
			customerCell=builder.setMandatory(true).build();	
	    	
	    }
	   
	   
		
	    
		
	  
	    
		formfield=new FormField[][]
		{
			{ customerId,customerName,customerCell }
	    };
		
		FlexForm form = new FlexForm(formfield,FormStyle.ROWFORM);
		panel=new FlowPanel();
		form.setWidth("98%");
		panel.add(form);
	  }
	
	/* (non-Javadoc)
	 * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
	 */
	@Override
	public HandlerRegistration addValueChangeHandler(ValueChangeHandler<PersonInfo> handler) 
	{
		return null;
	}

	/* (non-Javadoc)
	 * @see com.google.gwt.user.client.ui.HasValue#getValue()
	 */
	@Override
	public PersonInfo getValue() 
	{
	    PersonInfo entity = null;
	    int id=-1;
	    if((this.id.getText().trim().equals(""))==false)
	       id=Integer.parseInt(this.getId().getText().trim());
	    
	    entity=idToPersonInfo.get(id);
	    return entity;
	}
	
	
	public int getIdValue()
	{
		if(this.id!=null)
		{
			String count=id.getText().trim();
			try{
			Integer intCount=Integer.parseInt(count);
			return intCount;
			}
			catch(Exception e)
			{
				return -1;
			}
			
			
		}
		return -1;
	}
	
	
	public Long getCellValue()
	{
		if(this.phone!=null)
		{
			String number=phone.getText().trim();
			try{
			Long longPhoneCount=Long.parseLong(number);
			return longPhoneCount;
			}
			catch(Exception e)
			{
				return -1L;
			}
			
			
		}
		return -1L;
	}
	
	
	public String getFullNameValue()
	{
		if(this.name!=null)
		{
			String name=this.name.getText().trim();
			return name;
		}
		return "";
			
	}
	
	public Vector<Filter> getQuerryFilters()
	{
		
		  Filter temp;
		  Vector<Filter>filtervec=new Vector<Filter>();
		  if(getIdValue()!=-1)
		  {
		  temp=new Filter();
		  temp.setIntValue(getIdValue());
		  temp.setQuerryString("personInfo.count");
		  filtervec.add(temp);
		  }
		  
		  if(!(getFullNameValue().equals("")))
		  {
		  temp=new Filter();
		  temp.setStringValue(getFullNameValue());
		  temp.setQuerryString("personInfo.fullName");
		  filtervec.add(temp);
		  }
		  if(getCellValue()!=-1l)
		  {
		  temp=new Filter();
		  temp.setLongValue(getCellValue());
		  temp.setQuerryString("personInfo.cellNumber");
		  filtervec.add(temp);
		  }
		  
		  return filtervec;
	}
	
	
	
	
	
	

	/* (non-Javadoc)
	 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object)
	 */
	@Override
	public void setValue(PersonInfo value) 
	{
		id.setText(value.getCount()+"");
		name.setValue(value.getFullName());
		phone.setText(value.getCellNumber()+"");
	}

	//Understand composites and use this power
	/* (non-Javadoc)
	 * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean)
	 */
	@Override
	public void setValue(PersonInfo value, boolean fireEvents) {
		
		
	}

	//Understand composites and use this power
	/* (non-Javadoc)
	 * @see com.google.gwt.event.logical.shared.SelectionHandler#onSelection(com.google.gwt.event.
	 * logical.shared.SelectionEvent)
	 */
	@Override
	public void onSelection(SelectionEvent<Suggestion> event) 
	{	
		SuggestBox sb=(SuggestBox) event.getSource();
		String selectedItem=sb.getText().trim();
		resetBorderColor(id);
		resetBorderColor(name);
		resetBorderColor(phone);
		if(sb==this.id)
		{
			int count=Integer.parseInt(selectedItem);
			centity=idToPersonInfo.get(count);
			
			if(centity==null)
				sb.setText("");
			else
			{	
				name.setText(centity.getFullName());
				phone.setText(centity.getCellNumber()+"");
			}
		}
		
		if(sb==this.phone)
		{
			Long  phone=Long.parseLong(selectedItem);
			centity=cellToPersonInfo.get(phone);
			
			if(centity==null)
				sb.setText("");
			
			else
			{
				name.setText(centity.getFullName());
				id.setText(centity.getCount()+"");
			}
		}
		
		if(sb==this.name)
		{
			String[]xyz=selectedItem.split("-");
			
			if(xyz.length==0)
			{
				sb.setText("");
				return;	
			}
			
			else
			{
				centity=nameToPersonInfo.get(selectedItem);
				
				if(centity==null)
					sb.setText("");
				
				else
				{
					phone.setText(centity.getCellNumber()+"");
					id.setText(centity.getCount()+"");
					this.name.setText(centity.getFullName());
				}
			}
		}
	}
	
	
	/**
	 * Sets the color border.
	 *
	 * @param widget the widget
	 * @param color the color
	 */
	public void setColorBorder(Widget widget,String color)
	{
		widget.getElement().getStyle().setBackgroundColor(color);
	}

	/* (non-Javadoc)
	 * @see com.simplesoftwares.client.library.composite.CompositeInterface#clear()
	 */
	public void clear()
	{
		int row=this.formfield.length;
		for(int k=0;k<row;k++)
		{
			int column=formfield[k].length;
			for(int i=0;i<column;i++)
			{
				Widget widg=formfield[k][i].getWidget();
				if(widg instanceof SuggestBox)
				{
					SuggestBox sb=(SuggestBox) widg;
					resetBorderColor(sb);
					sb.setText("");
					
					
				}
				
				if(formfield[k][i].getMandatoryMsgWidget()!=null)
					formfield[k][i].getMandatoryMsgWidget().setVisible(false);
					
					
				
				
				}
			}
		}					
	
	 
 	/**
 	 * Change background color.
 	 *
 	 * @param widg the widg
 	 * @param color the color
 	 */
 	private void changeBorderColor(Widget widg,String color)
	 {
		 widg.getElement().getStyle().setBorderColor(color);
	 }
	 
	 /**
 	 * Clear background color.
 	 *
 	 * @param widg the widg
 	 */
 	private void resetBorderColor(Widget widg)
	 {
		 widg.getElement().getStyle().clearBorderColor();
		
		 
	 }
		
	 
	 /**
 	 * Sets the enabled.
 	 *
 	 * @param status the new enabled
 	 */
 	public void setEnabled(boolean status)
 	{
		 this.id.setEnabled(status);
		 this.name.setEnabled(status);
		 this.phone.setEnabled(status);
		 
 	}
	 
	 /**
 	 * Initalize person info hash maps.
 	 */
 	public void initalizePersonInfoHashMaps()
	{	 
 		PersonInfoServiceAsync  personservice=GWT.create(PersonInfoService.class);
		
		personservice.LoadVinfo(querry, new AsyncCallback<ArrayList<PersonInfo>>() {
			@Override
			public void onFailure(Throwable caught) {
				
			}

			@Override
			public void onSuccess(ArrayList<PersonInfo> result) {
			
				for(int i=0;i<result.size();i++)
				{
					int id=result.get(i).getCount();
				
					String name=result.get(i).getFullName();
					Long cellno=result.get(i).getCellNumber();
					
					idToPersonInfo.put(id, result.get(i));
					nameToPersonInfo.put(name, result.get(i));
					cellToPersonInfo.put(cellno, result.get(i));
				}
				initalizeCellOracle();
				initalizeIdOracle();
				initalizeNameOracle();
			}
		});
	 }
	 
	 /**
 	 * Apply style.
 	 */
 	public void applyStyle()
 	{
		 panel.setWidth("98%");
 	}
	 
	 /**
 	 * Initalize name oracle.
 	 */
 	private void initalizeNameOracle()
 	{
		 MultiWordSuggestOracle orcl = (MultiWordSuggestOracle) this.name.getSuggestOracle();
		 
		 for(String name:nameToPersonInfo.keySet())
		   orcl.add(name);		 
		 
	 }
	 
	 /**
 	 * Initalize cell oracle.
 	 */
 	private void initalizeCellOracle()
 	{
		 MultiWordSuggestOracle orcl = (MultiWordSuggestOracle) this.phone.getSuggestOracle();
		 for(Long cell:this.cellToPersonInfo.keySet())
			 orcl.add(cell+"");
 	}
	 
	 /**
 	 * Initalize id oracle.
 	 */
 	private void initalizeIdOracle()
 	{
		 MultiWordSuggestOracle orcl = (MultiWordSuggestOracle) this.id.getSuggestOracle();
		 for(int id:this.idToPersonInfo.keySet())
			 orcl.add(id+"");	 
 	}

	/**
	 * Gets the id.
	 *
	 * @return the id
	 */
	public SuggestBox getId() {
		return id;
	}

	/**
	 * Sets the id.
	 *
	 * @param id the new id
	 */
	public void setId(SuggestBox id) {
		this.id = id;
	}

	/**
	 * Gets the name.
	 *
	 * @return the name
	 */
	public SuggestBox getName() {
		return name;
	}

	/**
	 * Sets the name.
	 *
	 * @param name the new name
	 */
	public void setName(SuggestBox name) {
		this.name = name;
	}

	/**
	 * Gets the phone.
	 *
	 * @return the phone
	 */
	public SuggestBox getPhone() {
		return phone;
	}

	/**
	 * Sets the phone.
	 *
	 * @param phone the new phone
	 */
	public void setPhone(SuggestBox phone) {
		this.phone = phone;
	}

	/**
	 * Gets the centity.
	 *
	 * @return the centity
	 */
	public PersonInfo getCentity() {
		return centity;
	}

	/**
	 * Sets the centity.
	 *
	 * @param centity the new centity
	 */
	public void setCentity(PersonInfo centity) {
		this.centity = centity;
	}

	/**
	 * Gets the id to person info.
	 *
	 * @return the id to person info
	 */
	public HashMap<Integer, PersonInfo> getIdToPersonInfo() {
		return idToPersonInfo;
	}

	/**
	 * Sets the id to person info.
	 *
	 * @param idToPersonInfo the id to person info
	 */
	public void setIdToPersonInfo(HashMap<Integer, PersonInfo> idToPersonInfo) {
		this.idToPersonInfo = idToPersonInfo;
	}

	/**
	 * Gets the cell to person info.
	 *
	 * @return the cell to person info
	 */
	public HashMap<Long, PersonInfo> getCellToPersonInfo() {
		return cellToPersonInfo;
	}

	/**
	 * Sets the cell to person info.
	 *
	 * @param cellToPersonInfo the cell to person info
	 */
	public void setCellToPersonInfo(HashMap<Long, PersonInfo> cellToPersonInfo) {
		this.cellToPersonInfo = cellToPersonInfo;
	}

	/**
	 * Gets the name to person info.
	 *
	 * @return the name to person info
	 */
	public HashMap<String, PersonInfo> getNameToPersonInfo() {
		return nameToPersonInfo;
	}

	/**
	 * Sets the name to person info.
	 *
	 * @param nameToPersonInfo the name to person info
	 */
	public void setNameToPersonInfo(HashMap<String, PersonInfo> nameToPersonInfo) {
		this.nameToPersonInfo = nameToPersonInfo;
	}

	/**
	 * Gets the panel.
	 *
	 * @return the panel
	 */
	public FlowPanel getPanel() {
		return panel;
	}

	/**
	 * Sets the panel.
	 *
	 * @param panel the new panel
	 */
	public void setPanel(FlowPanel panel) {
		this.panel = panel;
	}

	/**
	 * Gets the ff.
	 *
	 * @return the ff
	 */
	public FormField[][] getFf() {
		return formfield;
	}

	/**
	 * Sets the ff.
	 *
	 * @param ff the new ff
	 */
	public void setFf(FormField[][] ff) {
		this.formfield = ff;
	}

	/**
	 * Gets the service.
	 *
	 * @return the service
	 */
	public PersonInfoServiceAsync getService() {
		return service;
	}

	/* (non-Javadoc)
	 * @see com.simplesoftwares.client.library.composite.CompositeInterface#setEnable(boolean)
	 */
	@Override
	public void setEnable(boolean status) 
	{
		this.id.setEnabled(status);
		this.name.setEnabled(status);
		this.phone.setEnabled(status);
	}

	/* (non-Javadoc)
	 * @see com.simplesoftwares.client.library.composite.CompositeInterface#validate()
	 */
	@Override
	public boolean validate() 
	{
		if(isValidate==false)
			return true;
		int count=0;
		boolean result=true;
		//this try-catch is checking if id contains any number format value or not.
		try
		{
			count=Integer.parseInt(this.id.getText().trim());
		}
		catch(Exception e)
		{
			changeBorderColor(this.name,"#dd4b39");
			changeBorderColor(this.phone,"#dd4b39");
			changeBorderColor(this.id,"#dd4b39");
			
			InlineLabel lbl=formfield[0][0].getMandatoryMsgWidget();
			
			if(this.id.getText().trim().equals(""))
				lbl.setVisible(true);
			
			else
			{	
				lbl.setText("Id not in Proper Format!");
				lbl.setVisible(true);
			}
			
			return false;
		}
		
		//it will be null if id value is in number format but not in present in db.
		PersonInfo info=idToPersonInfo.get(count);
		
		if(info==null)
		{
			result=false;
			changeBorderColor(this.name,"#dd4b39");
			changeBorderColor(this.phone,"#dd4b39");
			changeBorderColor(this.id,"#dd4b39");
			
			InlineLabel lbl=formfield[0][0].getMandatoryMsgWidget();
			lbl.setText("Given Id does not match in Database!");
			lbl.setVisible(true);
			
			return result;
		}
		
		//we are here, it means first user put right value in id field.
		
		//now check for if he/she changed either any value after the correct suggestion.
		
		String name=info.getFullName();
		
		String cell=info.getCellNumber()+"";
		
		String ids=info.getCount()+"";
		
		InlineLabel lbl=formfield[0][0].getMandatoryMsgWidget();
		
		if(this.name.getText().trim().contains(name)==false)
		{
			result=false;
			changeBorderColor(this.name,"#dd4b39");
			
			lbl.setText("Given name does not match in Database!");
			lbl.setVisible(true);
		}
		
		if(this.phone.getText().trim().equals(cell)==false)
		{
			result=false;
			changeBorderColor(this.phone,"#dd4b39");
			
			lbl.setText("Given cell number does not match in Database!");
			lbl.setVisible(true);
		}
		
		if(this.id.getText().trim().equals(ids)==false)
		{
			result=false;
			changeBorderColor(this.id,"#dd4b39");
			
			lbl.setText("Given Id does not match in Database!");
			lbl.setVisible(true);
		}
		
		return result;
	}
	
	public void makeMandatoryMessageFalse()
	{
		
		if(customerId!=null&&customerId.getMandatoryMsgWidget()!=null)
		{
			customerId.getMandatoryMsgWidget().setVisible(false);
		}
		
		if(customerName!=null&&customerName.getMandatoryMsgWidget()!=null)
		{
			customerName.getMandatoryMsgWidget().setVisible(false);
		}
		
		if(customerCell!=null&&customerCell.getMandatoryMsgWidget()!=null)
		{
			customerCell.getMandatoryMsgWidget().setVisible(false);
		}
	}

	public FormField getCustomerId() {
		return customerId;
	}

	public void setCustomerId(FormField customerId) {
		this.customerId = customerId;
	}

	public FormField getCustomerName() {
		return customerName;
	}

	public void setCustomerName(FormField customerName) {
		this.customerName = customerName;
	}

	public FormField getCustomerCell() {
		return customerCell;
	}

	public void setCustomerCell(FormField customerCell) {
		this.customerCell = customerCell;
	}

	public FormField[][] getFormfield() {
		return formfield;
	}

	public void setFormfield(FormField[][] formfield) {
		this.formfield = formfield;
	}

	public boolean isMandatory() {
		return mandatory;
	}

	public void setMandatory(boolean mandatory) {
		this.mandatory = mandatory;
	}

	public boolean isValidate() {
		return isValidate;
	}

	public void setValidate(boolean isValidate) {
		this.isValidate = isValidate;
	}
	
	private static class NumbersOnly implements KeyPressHandler {
	    @Override
	    public void onKeyPress(KeyPressEvent event) 
	    {
	    	if(!(Character.isDigit(event.getCharCode()) ||event.getCharCode()=='.'))
	        	{
	    		TextBox v=(TextBox) event.getSource();
	    		v.cancelKey();
	    		System.out.println("Cancelled");
	    		}
	    }
	    
	    
	}
}